package org.example.service;

import dev.langchain4j.model.chat.ChatLanguageModel;
import dev.langchain4j.model.chat.StreamingChatLanguageModel;
import dev.langchain4j.model.chat.response.ChatResponse;
import dev.langchain4j.model.chat.response.StreamingChatResponseHandler;

import org.example.config.AssistantApi;
import org.example.model.AvatarSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.FluxSink;
import reactor.util.retry.Retry;

import java.time.Duration;

@Service
public class ChatService {

    private final static Logger logger = LoggerFactory.getLogger(ChatService.class);

    @Autowired
    private StreamingChatLanguageModel streamingModel;

    @Autowired
    private ChatLanguageModel chatModel;

    @Autowired
    private AssistantApi assistant;

    @Autowired
    private AvatarSessionManager avatarSessionManager;

    // 设置10秒超时
    private static final Duration TIMEOUT_DURATION = Duration.ofSeconds(10);
    private static final int MAX_RETRIES = 1;
    private static final Duration INITIAL_BACKOFF = Duration.ofSeconds(1);

    public String getResponse(String userInput) {
        try {
            return chatModel.chat(userInput);
        } catch (Exception e) {
            logger.error("Error during chat processing", e);
            return "{\"error\": \"" + e.getMessage() + "\"}";
        }
    }

    public Flux<String> getResponseStream(String userInput) {
        return applyResiliencePattern(createResponseFlux(userInput));
    }

    public Flux<String> getAssistantResponseStream(String userInput) {
        return applyResiliencePattern(createStreamingAssistantResponseFlux(userInput));
    }

    private <T> Flux<T> applyResiliencePattern(Flux<T> flux) {
        return flux.timeout(TIMEOUT_DURATION)
                .onErrorMap(throwable -> {
                    if (throwable instanceof java.util.concurrent.TimeoutException) {
                        return new RuntimeException("请求超时，请稍后重试");
                    }
                    return new RuntimeException(throwable.getMessage());
                })
                .retryWhen(Retry.backoff(MAX_RETRIES, INITIAL_BACKOFF)
                        .filter(throwable -> !(throwable instanceof java.util.concurrent.TimeoutException))
                        .doBeforeRetry(
                                retrySignal -> System.out.println("[ChatService] Retrying after failure. Attempt: "
                                        + (retrySignal.totalRetries() + 1)))
                        .onRetryExhaustedThrow((retryBackoffSpec, retrySignal) -> {
                            System.err.println("[ChatService] All retry attempts exhausted");
                            return retrySignal.failure();
                        }));
    }

    private Flux<String> createResponseFlux(String userInput) {
        // 正常处理流程
        return Flux.create(sink -> {
            try {
                streamingModel.chat(userInput, new StreamingChatResponseHandler() {
                    @Override
                    public void onPartialResponse(String partialResponse) {
                        if (partialResponse != null && !partialResponse.isEmpty()) {
                            sink.next(partialResponse);
                        }
                    }

                    @Override
                    public void onCompleteResponse(ChatResponse chatResponse) {
                        sink.complete();
                    }

                    @Override
                    public void onError(Throwable error) {
                        sink.error(error);
                    }
                });
            } catch (Exception e) {
                sink.error(e);
            }
        }, FluxSink.OverflowStrategy.BUFFER);
    }

    /**
     * 使用 assistant 的原生流式响应能力
     * 
     * @param userMessage 用户消息
     * @return 响应字符串的 Flux 流
     */
    private Flux<String> createStreamingAssistantResponseFlux(String userMessage) {
        return assistant.chat(userMessage);
    }

    /**
     * 处理需要数字人播报的消息
     */
    public void processWithAvatar(String userMessage, String aiResponse) {
        try {
            // 检查是否有活跃会话，如果没有则创建
            String sessionId = getOrCreateAvatarSession();

            // 让数字人播报AI的回复
            avatarSessionManager.sendText(sessionId, aiResponse, true);

        } catch (Exception e) {
            // 记录异常，但不影响原有流程
            logger.error("数字人播报失败", e);
        }
    }

    private String getOrCreateAvatarSession() throws Exception {
        // 这里可以从用户会话中获取现有的数字人会话ID
        // 如果没有则创建新的会话

        // 示例实现
        AvatarSession session = avatarSessionManager.createSession();
        return session.getSessionId();
    }
}